package com.tim.javaApi.reflect;


import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Description:
 * @Version 1.0, 2021/9/25
 * @Author Tim
 */
public class ProxyDemo {
    
    public void staticProxy(){
        Person originPerson = new Person.Teacher();
        Person staticProxyPerson = new StaticProxyPerson(originPerson);
        originPerson.showName();
        staticProxyPerson.showName();
    }

    
    public void javaDynamicProxy(){
        Person originPerson = new Person.Teacher();
        InvocationHandler invocationHandler = new PersonInvocationHandlerImpl(originPerson);
        Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{Person.class}, invocationHandler);
        ((Person)proxy).showName();
    }

    class PersonInvocationHandlerImpl implements InvocationHandler {
        private Person originPerson;

        public PersonInvocationHandlerImpl(Person originPerson) {
            this.originPerson = originPerson;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(proxy.getClass().getCanonicalName());
            method.invoke(originPerson, args);
            return null;
        }
    }

    
    public void cglibDynamicProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Person.Teacher.class);
        MethodInterceptor methodInterceptor = new MethodInterceptor() {
            // method父类方法
            // methodProxy子类方法
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("MethodInterceptor1");
                methodProxy.invokeSuper(o, objects);
                return null;
            }
        };
        enhancer.setCallback(methodInterceptor);
        Object proxy = enhancer.create();
        ((Person)proxy).showName();
    }

    class StaticProxyPerson implements Person{
        private Person originPerson;

        public StaticProxyPerson(Person originPerson){
            this.originPerson = originPerson;
        }

        @Override
        public void showName() {
            System.out.print("StaticProxyPerson: ");
            originPerson.showName();
        }
    }

}
